package redis

import com.google.protobuf.Message
import io.netty.buffer.ByteBuf
import io.netty.buffer.ByteBufAllocator
import io.netty.buffer.ByteBufInputStream
import io.netty.buffer.ByteBufOutputStream
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.decodeFromByteArray
import kotlinx.serialization.encodeToByteArray
import kotlinx.serialization.protobuf.ProtoBuf
import org.example.seri.Data
import org.redisson.client.codec.BaseCodec
import org.redisson.client.protocol.Decoder
import org.redisson.client.protocol.Encoder
import java.io.IOException

class ProtobufCodec() : BaseCodec() {
    @OptIn(ExperimentalSerializationApi::class)
    private val encoder = Encoder { in1 ->
        val msg = in1 as Data
        val out = ByteBufAllocator.DEFAULT.buffer()
        val output = ByteBufOutputStream(out)
        try {
            val bytes = ProtoBuf.encodeToByteArray(msg)
            output.write(bytes)
            out
        } catch (e: IOException) {
            out.release()
            throw e
        } finally {
            output.close()
        }
    }

    @OptIn(ExperimentalSerializationApi::class)
    private val decoder = Decoder<Any> { buf, state ->
        val input = ByteBufInputStream(buf as ByteBuf)
        try {
            val data = ProtoBuf.decodeFromByteArray<Data>(input.readAllBytes())
            data
        } catch (e: IOException) {
            throw e
        } finally {
            input.close()
        }
    }

    override fun getValueEncoder(): Encoder {
        return encoder
    }

    override fun getValueDecoder(): Decoder<Any> {
        return decoder
    }
}